﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Convertor.Interface;
using Wpf.CommonTools.SystemExtension;
using System.Windows;

namespace Convertor.Plugin.InsertText
{
    public class Plugin : PluginBase
    {

        #region Static Func

        static string[] LanguagePaths = new string[] { @"Convertor.Plugin.InsertText;component\Assets\Lang\StringResource.zh.xaml", @"Convertor.Plugin.InsertText;component\Assets\Lang\StringResource.en.xaml" };

        static Plugin()
        {
            foreach (string path in LanguagePaths)
            {
                ResourceDictionary resourceDictionary = new ResourceDictionary();
                resourceDictionary.Source = new Uri(path, UriKind.Relative);
                Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
            }
        }

        #endregion

        #region IPluginInfo 成员

        public override string Name
        {
            get { return UILanguage.FindResource("PluginType_Text") + " - " + UILanguage.FindResource("Plugin_InsertText_Name"); }
        }

        public override string Description
        {
            get { return UILanguage.FindResource("Plugin_InsertText_Desc"); }
        }


        

        

        #endregion

        #region IConvertParamters 成员

        public override IConvertParamters Output(IConvertParamters content)
        {
            if (content == null || content.OutputContent == null)
            {
                if (Log != null) { Log(this, UILanguage.FindResource("Plugin_Common_Input_Output_Null"), LogTypes.Error); }
                content.StopConvert = true;
                return content;
            }
            string oldStr = content.OutputContent.ToString();
            string newStr;


            switch (config.CalculateType)
            {
                default:
                case CalculateTypes.Char:
                    newStr = charFunc(oldStr);
                    break;
                case CalculateTypes.Line:
                    newStr = lineFunc(oldStr);
                    break;
            }

            if (Log != null) { Log(this, config.ToolTip, LogTypes.Normal); }

            return new ConvertParamters(content.LastInputContent, newStr);
        }

        private string lineFunc(string oldStr)
        {
            string[] newStr = Regex.Split(oldStr, "\r\n");
            int startPosition, stopPosition;
            int offset = config.Length ?? 0;

            switch (config.StartType)
            {
                default:
                case StartTypes.Start:
                    startPosition = config.StartPosition ?? 0;
                    stopPosition = startPosition + offset;
                    break;
                case StartTypes.End:
                    startPosition = newStr.Length - (config.StartPosition ?? 0);
                    stopPosition = startPosition + offset;
                    break;
            }
            StringBuilder sb = new StringBuilder();
            switch (config.InsertType)
            {
                default:
                case InsertTypes.Insert:
                    int i = 0;
                    foreach (string str in newStr)
                    {
                        if (i == startPosition)
                        {
                            sb.AppendLine(config.InsertText ?? string.Empty);
                        }
                        sb.AppendLine(str);
                        i++;
                    }
                    if (i == startPosition)
                    {
                        sb.AppendLine(config.InsertText ?? string.Empty);
                    }
                    break;
                case InsertTypes.Delete:
                    //length = Math.Max(0, Math.Min(newStr.Length - startPosition, length));
                    i = 0;
                    foreach (string str in newStr)
                    {
                        if (i < startPosition || i >= stopPosition)
                        {
                            sb.AppendLine(str);
                        }
                        i++;
                    }
                    break;
                case InsertTypes.Move:

                    if (config.StartType == StartTypes.End)
                    {
                        startPosition--;
                    }
                    string strTemp = moveLine(newStr, startPosition, offset);
                    sb.Append(strTemp);
                    break;
            }
            return sb.ToString();
        }

        private string charFunc(string oldStr)
        {
            string newStr;
            int startPosition, length;

            switch (config.StartType)
            {
                default:
                case StartTypes.Start:
                    startPosition = config.StartPosition ?? 0;
                    break;
                case StartTypes.End:
                    startPosition = oldStr.Length - (config.StartPosition ?? 0);
                    break;
            }
            startPosition = Math.Max(0, Math.Min(oldStr.Length, startPosition));
            length = config.Length ?? 0;

            switch (config.InsertType)
            {
                default:
                case InsertTypes.Insert:
                    newStr = oldStr.Insert(startPosition, config.InsertText ?? string.Empty);
                    break;
                case InsertTypes.Delete:
                    length = Math.Max(0, Math.Min(oldStr.Length - startPosition, length));
                    newStr = oldStr.Remove(startPosition, length);
                    break;
                case InsertTypes.Move:
                    if (config.StartType == StartTypes.End)
                    {
                        startPosition--;
                    }
                    newStr = moveCharTo(oldStr, startPosition, length);
                    break;
            }
            return newStr;
        }

        private string moveCharTo(string str, int positionA, int offset)
        {
            int length = str.Length;
            if (positionA >= length)
            {
                positionA = length - 1;
            }
            if (positionA < 0)
            {
                positionA = 0;
            }

            StringBuilder sb = new StringBuilder(length);
            int positionB = positionA + offset;

            string a = str.Substring(positionA, 1);
            int i = 0;
            if (offset >= 0)
            {
                foreach (var b in str)
                {
                    if (i != positionA)
                    {
                        sb.Append(b);
                    }

                    if (i == positionB)
                    {
                        sb.Append(a);
                    }
                    i++;
                }
            }
            else
            {
                foreach (var b in str)
                {
                    if (i == positionB)
                    {
                        sb.Append(a);
                    }
                    if (i != positionA)
                    {
                        sb.Append(b);
                    }
                    i++;
                }
            }
            return sb.ToString();
        }

        private string moveLine(string[] str, int positionA, int offset)
        {
            int length = str.Length;
            if (positionA >= length)
            {
                positionA = length - 1;
            }
            if (positionA < 0)
            {
                positionA = 0;
            }

            StringBuilder sb = new StringBuilder(length);
            int positionB = positionA + offset;

            string a = str[positionA];
            int i = 0;
            if (offset >= 0)
            {
                foreach (var b in str)
                {
                    if (i != positionA)
                    {
                        sb.AppendLine(b);
                    }

                    if (i == positionB)
                    {
                        sb.AppendLine(a);
                    }
                    i++;
                }
            }
            else
            {
                foreach (var b in str)
                {
                    if (i == positionB)
                    {
                        sb.AppendLine(a);
                    }
                    if (i != positionA)
                    {
                        sb.AppendLine(b);
                    }
                    i++;
                }
            }
            return sb.ToString();
        }

        #endregion

        #region IPluginConfigForm 成员

        public override PluginConfigForm ConfigForm
        {
            get { return new ConfigForm(); }
        }

        #endregion

        #region IPluginConfig 成员

        private ConfigContent config;
        public override object Config
        {
            get { return config; }
            set { config = (value as ConfigContent) ?? new ConfigContent(); }
        }

        #endregion

    }
}
